require 'rubygems'
require 'net/http'
require 'uri'
require 'progressbar'
require 'rexml/document'
require 'content_data'

module PCLink

DEFAULT_MAX_NUMBER = 256

NODE_QUERY_MSG = <<EOF
<requestnavdata>
  <reqparameters>
    <fpsv>30</fpsv>
    <iamsv>101</iamsv>
    <nc12>313911855841</nc12>
    <setnc12>907310010777</setnc12>
    <uid>0</uid>
  </reqparameters>
  <nodeid>nodeid_value</nodeid>
  <fromindex>from_value</fromindex>
  <serviceid>1</serviceid>
  <numelem>count_value</numelem>
</requestnavdata>
EOF

  class Channel
    
    def initialize(options)
      if options[:connection]
        @connection = options[:connection] 
      elsif options[:host] && options[:port]
        host = options[:host]
        port = options[:port]
        @connection = HttpConnection.new(host, port)
      else 
        raise "Must specify a connection or host & port"
      end
    end

    def enable_progress_bar=(enabled)
      @enable_progress_bar = enabled
    end
    
    def list_node(nodeid = 0) 
      total = 9999 
      num = 0
      content_data = []
      progress_bar = nil
      while num < total do
        msg = create_request_message(nodeid.to_s, num, DEFAULT_MAX_NUMBER)
        resp = @connection.send_request(msg)
        doc = REXML::Document.new(resp)
        total = doc.root.elements["totnumelem"].text.to_i 
        num = num + doc.root.elements["numelem"].text.to_i
        doc.root.elements.each("//contentdata") do |el| 
          cd = ContentData.from_element(el) 
          cd.channel = self
          content_data <<  cd
        end
        update_status(num, total, progress_bar)
      end
      content_data
    end
  end
  
  private 
  def update_status(num, total, progress_bar) 
        if @enable_progress_bar && num > 0 && total/num > 2 && progress_bar == nil
          steps = (total/num) - 1
          progress_bar = ProgressBar.new("retrieving", steps)
        end
        if progress_bar
          progress_bar.inc 
        else 
          puts "received #{num} of #{total}"
        end
  end
  
  def get_value_of_element(xpath)
    val = nil
    doc.root.elements.each(xpath) { |e| val = e.text.to_i }
    val
  end
  
    
  def create_request_message(nodeid, from, count)
    msg = NODE_QUERY_MSG.gsub(/nodeid_value/, nodeid.to_s)
    msg.gsub!(/from_value/, from.to_s)
    msg.gsub!(/count_value/, count.to_s)
    msg
  end
  

  class HttpConnection
      def initialize(host, port)
        @host = host
        @port = port
      end

    def send_request(msg)
        url = URI.join("http://#{@host}", "/")
        http = Net::HTTP.new(@host, @port)
        res = http.post(url.request_uri, msg)
        res.body 
    end
  end

end